#!/usr/bin/env python
# -*- coding: utf-8; -*-
import datetime

from django.utils.deprecation import MiddlewareMixin
from django.conf import settings
from django.shortcuts import redirect

from web import models


class Tracer(object):
    def __init__(self):
        """封装用户对象、价格策略"""
        self.user = None
        self.package = None
        self.project = None


class AuthMiddleware(MiddlewareMixin):
    def process_request(self, request):
        """如果用户已登录，则 request 中赋值"""

        request.tracer = Tracer()

        userid = request.session.get('user_id', 0)
        user_obj = models.UserInfo.objects.filter(id=userid).first()
        request.tracer.user = user_obj

        #####################################################
        #           URL白名单拦截未登录或未注册的网址请求         #
        #####################################################

        # 为了防止没有登录时，无限制的重定向到 index 页面, 添加例外
        # 白名单

        if request.path_info in settings.WHITE_REGEX_URL_LIST:
            return None
        # 对于新用户注册请求，request 本中间件流程已全部走完('login'在白名单
        # 中)，进入下一个中间件，其他的url请求继续本方法下面的处理

        if not request.tracer.user:
            return redirect('login')

        ##########################################################
        #                 以下内容处理登录用户                       #
        ##########################################################

        # 登录成功后，获取当前用户拥有的额度，注意免费账户的交易状态 status 同样是 2
        # 查询用户的最新交易记录
        _object = models.Transaction.objects.filter(
            user=user_obj, status=2).order_by('-id').first()

        # 得到交易记录后，判断是否过期，注意免费账户的过期时间为空，需要排除
        current_datetime = datetime.datetime.now()
        if _object.end_datetime and _object.end_datetime < current_datetime:
            # 过期记录选择：
            _object = models.Transaction.objects.filter(
                user=user_obj, status=2, package__category=1).first()

        request.tracer.package = _object.package

    # 访问各项目时(url 以 manage 开头)顶栏会显示项目菜单(对应模板标签名为
    # 'manage_project')，同时这些菜单在 /project/list/ 或 /index/ 页面应该
    # 隐藏。因此这些菜单的显示要求母板文件 manage.html 中加入对 url 和项目
    # 与当前用户关系的检测和过滤，依据结果来判定是否渲染项目功能于顶栏上

    # 对 url 和请求权限的过滤，通常使用中间件。这里我们之所以不在
    # process_request 中处理，是因为URL路由关系匹配发生在在所有中间件
    # process_view处理后、所有中间件process_view处理前。process_view 可以得
    # 到HttpResponse对象经路由匹配后的URL路径信息

    def process_view(self, request, view_func, view_args, view_kwargs):
        """处理以 /manage/ 为开头的地址请求，项目与用户有关联时将项目对象封装到请求对象属性中"""

        # URL 分析
        if not request.path_info.startswith('/manage/'):
            return None

        # URL 以 manage 开头，则继续下面的步骤

        # project_id 由URL调度时匹配得到
        project_id = view_kwargs.get('project_id')
        # 继续判断项目是否由用户创建
        project_obj = models.Project.objects.filter(
            creator=request.tracer.user, id=project_id).first()

        if project_obj:
            # URL 中指定的项目由用户创建时，封装该项目到
            # request.tracer.project 属性上
            request.tracer.project = project_obj
            return None

        # 是否为用户参与的项目
        project_user_obj = models.ProjectUser.objects.filter(
            user=request.tracer.user, project_id=project_id).first()
        if project_user_obj:
            # URL 中指定的项目为用户参与项目时，封装该项目到
            # request.tracer.project 属性上
            request.tracer.project = project_user_obj.project
            return None

        return redirect('project_list')
